package com.dhcc.service;

import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

/**
 * 封装 Redis 操作的服务类，提供响应式的 Redis 操作方法。
 *
 * @ProjectName Dhcc-Cloud
 * @PackageName dhcc.com.service
 * @Title RedisService
 * @Date 2024/10/4 下午7:49
 * @Author LiuGuoting
 */
@Service
public class ReactiveRedisService {

    private final ReactiveRedisTemplate<String, Object> reactiveRedisTemplate;

    public ReactiveRedisService(ReactiveRedisTemplate<String, Object> redisTemplate) {
        this.reactiveRedisTemplate = redisTemplate;
    }

    /**
     * 保存数据到 Redis。
     *
     * @param key   键
     * @param value 值
     * @return 返回操作结果
     */
    public Mono<Boolean> save(String key, Object value) {
        return reactiveRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 保存数据到 Redis，并设置有效期。
     *
     * @param key       键
     * @param value     值
     * @param time      有效期的数量
     * @param unit      有效期的时间单位
     * @return 返回操作结果
     */
    public Mono<Boolean> saveWithExpire(String key, Object value, int time, TimeUnit unit) {
        // 将时间转换为 Duration
        Duration duration = Duration.ofMillis(unit.toMillis(time));
        return reactiveRedisTemplate.opsForValue()
                // 直接设置有效期
                .set(key, value, duration);
    }

    /**
     * 从 Redis 获取数据。
     *
     * @param key 键
     * @return 返回获取的值
     */
    public Mono<Object> get(String key) {
        return reactiveRedisTemplate.opsForValue().get(key);
    }

    /**
     * 删除 Redis 中的数据。
     *
     * @param key 键
     * @return 返回操作结果
     */
    public Mono<Boolean> delete(String key) {
        return reactiveRedisTemplate.opsForValue().delete(key);
    }

    /**
     * 更新 Redis 中的数据。
     *
     * @param key   键
     * @param value 新值
     * @return 返回操作结果
     */
    public Mono<Boolean> update(String key, Object value) {
        return reactiveRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 检查指定的键是否存在于 Redis 中。
     *
     * @param key 键
     * @return 存在返回 true，不存在返回 false
     */
    public Mono<Boolean> exists(String key) {
        return reactiveRedisTemplate.hasKey(key);
    }

    /**
     * 获取所有 Redis 中的键。
     *
     * @return 返回键的 Flux
     */
    public Flux<String> getAllKeys() {
        return reactiveRedisTemplate.keys("*").flatMap(Flux::just);
    }


    /**
     * 对指定键的值进行自增操作。
     *
     * @param key       键
     * @param increment 增加的值
     * @return 返回自增后的值
     */
    public Mono<Long> increment(String key, long increment) {
        return reactiveRedisTemplate.opsForValue().increment(key, increment);
    }

    /**
     * 清空 Redis 数据库。
     *
     * @return 返回操作结果
     */
    public Mono<Void> flushDb() {
        return reactiveRedisTemplate.getConnectionFactory()
                .getReactiveConnection()
                .serverCommands()
                .flushDb()
                .then();
    }

    /**
     * 设置键值的有效期。
     *
     * @param key      键
     * @param time 有效期
     * @param unit 时间单位
     * @return 返回操作结果
     */
    public Mono<Boolean> setExpire(String key, int time, TimeUnit unit) {
        // 将时间转换为 Duration
        Duration duration = Duration.ofMillis(unit.toMillis(time));
        return reactiveRedisTemplate.expire(key, duration);
    }
}
